﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using zjx.Wpf.Graffitiboard.Adorners;
using zjx.Wpf.Graffitiboard.Controls;
using zjx.Wpf.Graffitiboard.Core;

namespace zjx.Wpf.Graffitiboard
{
    public class Graffitiboard : InkCanvas
    {
        #region 字段
        private Point startPoint;
        #endregion

        #region 属性
        #region SelectionService
        private SelectionService selectionService;

        internal SelectionService SelectionService
        {
            get
            {
                if (selectionService == null)
                {
                    selectionService = new SelectionService(this);
                }

                return selectionService;
            }
        }
        #endregion
        #endregion

        #region override
        #region OnStrokeCollected
        protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)
        {
            this.Strokes.Remove(e.Stroke);
            GraffitiStroke stroke = new GraffitiStroke(e.Stroke);
            this.Children.Add(stroke);
            base.OnStrokeCollected(e);
        }
        #endregion

        #region 鼠标事件
        protected override void OnMouseDown(MouseButtonEventArgs e)
        {
            if (e.Source is Graffitiboard)
            {
                this.startPoint = e.GetPosition(this);
                if (this.EditingMode == InkCanvasEditingMode.None)
                {
                    this.SelectionService.ClearSelection();
                    Focus();

                    e.Handled = true;
                }
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.Source is Graffitiboard && e.LeftButton == MouseButtonState.Pressed)
            {
                if (this.EditingMode == InkCanvasEditingMode.None)
                {
                    // create rubberband adorner
                    AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
                    if (adornerLayer != null)
                    {
                        SelectAreaAdorner adorner = new SelectAreaAdorner(this, this.startPoint);
                        if (adorner != null)
                        {
                            adornerLayer.Add(adorner);
                        }
                    }

                    e.Handled = true;
                }
            }
        }
        #endregion
        #endregion

        #region Public Method
        #region UpdateSelection
        public void UpdateSelection(Point p)
        {
            List<ISelectable> selectItems = this.GetSelectedItems(p);
            foreach (ISelectable stroke in selectItems)
            {
                this.SelectionService.AddToSelection(stroke);
            }
        }
        #endregion
        #endregion

        #region Private Method
        #region GetSelectedItems
        private List<ISelectable> GetSelectedItems(Point p)
        {
            List<ISelectable> list = new List<ISelectable>();
            IEnumerable<ISelectable> items = this.Children.OfType<ISelectable>();
            if (items.Count() > 0)
            {
                foreach (ISelectable item in items)
                {
                    Rect rect = item.GetBounds();
                    if (rect.Contains(p))
                    {
                        list.Add(item);
                    }
                }
            }

            return list;
        }
        #endregion
        #endregion
    }
}
